#ifndef __CE_SCENE_BOUNDINGBOX_H__
#define __CE_SCENE_BOUNDINGBOX_H__

#include <stdio.h>
#include <export.h>
#include <math/matrix.h>
#include <math/vector.h>

class ceRay;

/**
 * \addtogroup math
 * @{
 */
/**
 * @brief Implementation of an axis aligned bounding box for fast clipping.
 */
class CE_API ceBoundingBox
{
private:
  ceVector3f _min;
  ceVector3f _max;
  ceVector3f _center;
  bool    _clean;

  ceVector3f _points[8];

public:
    ceBoundingBox();

    void Add (float x, float y, float z);
    void Add (const ceVector3f& v);
    void Add (const ceBoundingBox& bbox);

    void Add (const ceMatrix4f& base, float x, float y, float z);
    void Add (const ceMatrix4f& base, const ceVector3f& v);
    void Add (const ceMatrix4f& base, const ceBoundingBox& bbox);

    void AddMargin (const ceVector3f& margin);

    void Update ();

    void Clear ();


    bool Hit (const ceRay& ray) const;

    const ceVector3f& GetMin () const
    {
      return _min;
    }

    const ceVector3f& GetMax () const
    {
      return _max;
    }

    const ceVector3f& GetCenter () const
    {
      return _center;
    }

    bool IsClean () const
    {
      return _clean;
    }

    const ceVector3f* GetPoints () const
    {
      return _points;
    }

    void Debug (const char* msg = 0) const
    {
      if (msg)
        {
          printf ("%s: ", msg);
          fflush(stdout);
        }
      printf ("<%.2f %.2f %.2f> - <%.2f %.2f %.2f>\n", _min.x, _min.y, _min.z, _max.x, _max.y, _max.z);
      fflush(stdout);
    }

    float GetInnerRadius () const
    {
      return (_max - _center).Min();
    }

    float GetOuterRadius () const
    {
      return (_max - _center).Length();
    }

    float GetMediumRadius () const
    {
      return (GetInnerRadius() + GetOuterRadius()) / 2.0f;
    }
};

/** @} */

#endif /* ! __CE_SCENE_BOUNDINGBOX_H__ */

